// (C) Szymon Piechowicz, February 2012

#include "hall_sensor.h"
#include "adc_manager.h"
#include "common.h"


#define HALL_SENSOR_FIELD_ADC_PORT PORTA
#define HALL_SENSOR_FIELD_ADC_PORT_DIR DDRA
#define HALL_SENSOR_FIELD_ADC_BIT PA5

#define FIELD_ADC_THRESHOLD 51 // 1 V
#define FIELD_ADC_MIN_CHANGE 10


static void field_adc_callback(int8_t bit, uint8_t result);


static hall_sensor_field_callback field_callback;
// Callbacks are fired only when field state changes.
static bool field_did_report_first_result;
static bool field_last_reported_result;


void hall_sensor_init(void)
{
  PORT_OFF(HALL_SENSOR_FIELD_ADC_PORT, HALL_SENSOR_FIELD_ADC_BIT);
}

void hall_sensor_start_measuring_field(hall_sensor_field_callback callback)
{
  field_callback = callback;
  field_did_report_first_result = false;
  adc_manager_start_measuring(HALL_SENSOR_FIELD_ADC_BIT, field_adc_callback,
      FIELD_ADC_MIN_CHANGE);
}

void hall_sensor_stop_measuring_field(void)
{
  adc_manager_stop_measuring(HALL_SENSOR_FIELD_ADC_BIT);
}

static void field_adc_callback(int8_t bit, uint8_t result)
{
  bool is_field_detected = (result <= FIELD_ADC_THRESHOLD);
  if (!field_did_report_first_result
      || is_field_detected != field_last_reported_result)
  {
    field_did_report_first_result = true;
    field_last_reported_result = is_field_detected;
    field_callback(is_field_detected);
  }
}